package de.umr.fb12.vs.os;

abstract class Syscall {
	static enum TYPES {
		YIELD, IOREQ, DUMMY, EXIT, EXECVE
	}

	final static int SC_YIELD = 0;
	final static int SC_IOREQ = 1;
	final static int SC_DUMMY = 2;
	final static int SC_EXIT = 3;
	final static int SC_EXECVE = 4;

	// pseudo syscalls NOTE THEY CAN FAIL return raises PendingIRQException
	// TODO search for better solution in java simulation
	final static void do_IO_req(final Task task, long time) {
		if (task.cpu.irq_ctrl.lock.tryAcquire()) {
			do_syscall(task, TYPES.IOREQ, null);
			task.iow += time * 1000;
			task.cpu.irq_ctrl.start_async_io(task, time);
		} else
			throw new CPU.PendingIRQException();

	}

	final static void do_dummy(final Task task) {
		if (task.cpu.irq_ctrl.lock.tryAcquire()) {
			do_syscall(task, TYPES.DUMMY, null);
		} else
			throw new CPU.PendingIRQException();
	}

	final static void do_yield(final Task task) {
		if (task.cpu.irq_ctrl.lock.tryAcquire()) {
			do_syscall(task, TYPES.YIELD, null);
		} else
			throw new CPU.PendingIRQException();
	}

	final static void do_exit(final Task task) {
		if (task.cpu.irq_ctrl.lock.tryAcquire()) {
			do_syscall(task, TYPES.EXIT, null);
		} else
			throw new CPU.PendingIRQException();
	}

	final static void do_execve(final Task task, int programNumber) {
		if (task.cpu.irq_ctrl.lock.tryAcquire()) {
			do_syscall(task, TYPES.EXECVE, programNumber);
		} else
			throw new CPU.PendingIRQException();
	}

	final static void do_syscall(final Task task, TYPES type,
			Object syscall_data) {
		// can only use handle_irq as entry if no active real irqs
		long b = System.nanoTime();
		task.syscall_data = syscall_data;
		task.syscall = type;
		task.cpu.irq_ctrl.IRQ_type = 0x80;
		task.cpu.irq_ctrl.dev = task;
		task.cpu.serve_irq();
		task.cpu.system += System.nanoTime() - b;
		task.cpu.irq_ctrl.lock.release();
	}

}
